package cn.tedu.justone.pack01;

/**
 * ZZ：JustOne
 * VX：Andylau2020smile
 * DY：JustOne2018
 * ZT：《》
 */
public class Demo19_测试i加加的原子性 {
    //
    //测试i++的原子性
    //测试i++的原子性
    //测试i++的原子性
    // 1,原子性，简单的可以理解为：操作是不可再分割的，例如 int i = 5;
    // 2,i++;是可以再分割的，它分为三步：
    //   a, 取出i的值5
    //   b, 执行5+1=6
    //   c, 把6赋给i存入内存
    //   也就是 i = i + 1;
    // 3,本例用于验证i++是不具有原子性的。我们创建100条线程去执行count++，
    //   预期值是10000，多测试几次，就会看到有不足1000的情况出现。
    // 4,不足1000，原因分析：
    //   是因为num++在多线程下是非线程安全的。 num++方法编译成字节码后，分为以下三步运行的：
    //   ---a,从主存中复制 i 的值并复制到 CPU 的工作内存中。
    //   ---b,CPU 取工作内存中的值，然后执行 i++操作，完成后刷新到工作内存。
    //   ---c,将工作内存中的值更新到主存。
    //   原本线程1在自己的工作空间中将num改为1，写回主内存，主内存由于内存可见性，
    //   通知线程2 3，num=1；线程2通过变量的副本拷贝，将num拷贝并++，num=2；
    //   再次写入主内存通知线程3，num=2，线程3通过变量的副本拷贝，将num拷贝并++，num=3；
    //   然而 多线程竞争调度的原因，1号线程刚刚要写1的时候被挂起，2号线程将1写入主内存，
    //   此时应该通知其他线程，主内存的值更改为1，由于线程操作极快，还没有通知到其他线程，
    //   刚才被挂起的线程1 将num=1 又再次写入了主内存，主内存的值被覆盖，出现了丢失写值；
    //   //看这里：景景神总结：先读的人，后写，导致写的是较早的结果。
    public static void main(String[] args) throws InterruptedException {
        MyThread[] arr = new MyThread[100];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new MyThread();
        }



        for (int i = 0; i < arr.length; i++) {
            arr[i].start();
        }

        Thread.sleep(1500);
        System.out.println("count 的最终值是："+MyThread.count);
    }
}

class MyThread extends Thread{
    public static int count = 0;
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            count++;
        }
        System.out.println("count = " + count);
    }
}




































